/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package database_client;

import DataObject.ServerInfo;
import DataObject.TableObject;
import Shared.PackageTransfer;
import Utility.ColorPane;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.swing.DefaultCellEditor;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTextField;

/**
 *
 * @author suzunghia
 */
public class MainFrame extends javax.swing.JFrame implements Runnable {

    /**
     * Creates new form MainFrame
     */
    PackageTransfer ob = null;
    ExecutorService exe;
    SSLSocketFactory ssf;
    SSLSocket sv;
    ObjectOutputStream oos;
    ObjectInputStream ois;
    JTable tables;
    Vector<TableObject> listObject;
    String[] tbHeader;
    Vector<ServerInfo> svInfo;
    private String databaseName;
    public String user;
    public String pass;
    public String ip;
    LogInScreen login;
    TreeInfo trees;
    private boolean isConnect = false;

    public MainFrame() {
        login = new LogInScreen();
        trees = new TreeInfo();
        initComponents();
        jScrollPane3.setViewportView(trees.treePanel);
        tables = new JTable();
        listObject = new Vector<>();
        //Database name 2 query
        databaseName = "Database";
        svInfo = new Vector<>();
        InitTable();
    }

    public void Connect() {
        System.setProperty("javax.net.ssl.trustStore", "myServerKS");
        System.setProperty("javax.net.ssl.trustStorePassword", "0912328");
        exe = Executors.newFixedThreadPool(1);
        int port = 3333;
        if (!ConnectServer(ip, port)) {
            JOptionPane.showMessageDialog(null, "Wrong something! Try again (File >> Log in)");
        } else {
            JOptionPane.showMessageDialog(null, "Connect success!");
            isConnect = true;
            databaseBox.removeAllItems();
            for (int i = 0; i < svInfo.size(); i++) {
                databaseBox.addItem(svInfo.get(i).databasesName);
            }
        }
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        Lb_run = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        LB_cancel = new javax.swing.JLabel();
        databaseBox = new javax.swing.JComboBox();
        jLabel1 = new javax.swing.JLabel();
        jScrollPane3 = new javax.swing.JScrollPane();
        jLabel2 = new javax.swing.JLabel();
        jMenuBar1 = new javax.swing.JMenuBar();
        Mn_Query = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();
        Mn_Exit = new javax.swing.JMenu();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        Lb_run.setIcon(new javax.swing.ImageIcon(getClass().getResource("/database_client/resource/run.png"))); // NOI18N
        Lb_run.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                Lb_runMouseClicked(evt);
            }
        });

        EditorQuery = new ColorPane();
        jScrollPane2.setViewportView(EditorQuery);
        EditorQuery.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                EditorQuery.EditorQueryKeyPressed(evt);
            }
        });

        LB_cancel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/database_client/resource/cancel.png"))); // NOI18N
        LB_cancel.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                LB_cancelMouseClicked(evt);
            }
        });

        databaseBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                databaseBoxItemStateChanged(evt);
            }
        });

        jLabel1.setFont(new java.awt.Font("Times New Roman", 1, 14)); // NOI18N
        jLabel1.setText("Select Database:");

        jLabel2.setFont(new java.awt.Font("Times New Roman", 1, 14)); // NOI18N
        jLabel2.setForeground(new java.awt.Color(12, 12, 202));
        jLabel2.setText("Database Info");

        Mn_Query.setText("File");

        jMenuItem1.setText("Log in");
        jMenuItem1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                jMenuItem1MousePressed(evt);
            }
        });
        jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem1ActionPerformed(evt);
            }
        });
        Mn_Query.add(jMenuItem1);

        jMenuBar1.add(Mn_Query);

        Mn_Exit.setText("Edit");
        jMenuBar1.add(Mn_Exit);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 108, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(databaseBox, javax.swing.GroupLayout.PREFERRED_SIZE, 209, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(Lb_run)
                        .addGap(18, 18, 18)
                        .addComponent(LB_cancel)
                        .addGap(12, 12, 12))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jScrollPane1)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 211, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 490, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(0, 0, Short.MAX_VALUE)))
                        .addContainerGap())))
            .addGroup(layout.createSequentialGroup()
                .addGap(40, 40, 40)
                .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 108, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 0, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(LB_cancel)
                    .addComponent(Lb_run)
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addGap(11, 11, 11)
                                .addComponent(jLabel1))
                            .addComponent(databaseBox, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE))))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 12, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 279, Short.MAX_VALUE)
                    .addComponent(jScrollPane2))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 187, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void Lb_runMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_Lb_runMouseClicked
        // TODO add your handling code here:                
        /*
         * ParseDatabase parse = new ParseDatabase(); parse.Connect();
         * parse.CreateDatabase("HOCSINH", "");
         */

        // CryptoFile crypto = new CryptoFile();

        //crypto.Decrypt("30532128", "D:/file.txt");
        if (Lb_run.isEnabled()) {
            Lb_run.setEnabled(false);
            EditorQuery.setEnabled(false);
            ClearTable();
            jScrollPane1.paintAll(jScrollPane1.getGraphics());
            Thread t = new Thread(this);
            t.start();
        }
    }//GEN-LAST:event_Lb_runMouseClicked

    private void LB_cancelMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_LB_cancelMouseClicked
        // TODO add your handling code here:
        EditorQuery.setText("");
    }//GEN-LAST:event_LB_cancelMouseClicked

    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        // TODO add your handling code here:
        exe.shutdown();        
        if (sv != null && !sv.isClosed()) {
            try {
                sv.close();
            } catch (IOException ex) {
                System.out.println(ex);
            }
        }
        MainFrame.this.dispose();
        System.exit(0);
    }//GEN-LAST:event_formWindowClosing

    private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem1ActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_jMenuItem1ActionPerformed

    private void jMenuItem1MousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jMenuItem1MousePressed
        // TODO add your handling code here:
        if (!isConnect) {
            login = new LogInScreen();
            login.ShowGUI(this);
            Connect();
        }
    }//GEN-LAST:event_jMenuItem1MousePressed

    private void databaseBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_databaseBoxItemStateChanged
        // TODO add your handling code here:
        databaseName = (String) databaseBox.getSelectedItem();
        trees.setTree(svInfo.get(databaseBox.getSelectedIndex()));
    }//GEN-LAST:event_databaseBoxItemStateChanged

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                MainFrame main = new MainFrame();
                main.setVisible(true);
                main.login.ShowGUI(main);
                main.Connect();
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel LB_cancel;
    private javax.swing.JLabel Lb_run;
    private javax.swing.JMenu Mn_Exit;
    private javax.swing.JMenu Mn_Query;
    private javax.swing.JComboBox databaseBox;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    // End of variables declaration//GEN-END:variables
    private ColorPane EditorQuery;

    private boolean ConnectServer(String string, int port) {
        try {
            try {
                //Create Socket       
                ssf = (SSLSocketFactory) SSLSocketFactory.getDefault();
                sv = (SSLSocket) ssf.createSocket(string, port);
                //Get read and write stream
                oos = new ObjectOutputStream(sv.getOutputStream());
                ois = new ObjectInputStream(sv.getInputStream());
            } catch (IOException ex) {
                String err = "Cannot connect to server\n Check info and try again";
                JOptionPane.showMessageDialog(this, err, "Report", JOptionPane.WARNING_MESSAGE);
                return false;
            }
            //Send account verify
            PackageTransfer pk = new PackageTransfer("jav");
            String[] account = new String[2];
            account[0] = user;
            account[1] = pass;
            pk.datas = account;
            oos.writeObject(pk);
            oos.flush();

            //Read success connect
            String str = null;
            try {
                PackageTransfer s = (PackageTransfer) ois.readObject();
                str = s.header;
                svInfo = (Vector<ServerInfo>) s.datas;
            } catch (IOException | ClassNotFoundException ex) {
                String err = "Parse data connect error";
                JOptionPane.showMessageDialog(this, err, "Report", JOptionPane.ERROR_MESSAGE);
                return false;
            }
            if (str != null) {
                //Check connect success
                if (str.compareToIgnoreCase("sc") == 0 && !sv.isClosed()) {
                    //Create listen thread
                    ListenFromServerRunable listen = new ListenFromServerRunable(ois, this);
                    exe.execute(listen);
                } else {
                    return false;
                }
            }
            return true;
        } catch (IOException ex) {
            System.out.println(ex.toString());
            return false;
        }
    }

    @Override
    public synchronized void run() {
        if (!sv.isClosed()) {
            try {
                String qr = EditorQuery.getText();
                PackageTransfer pk = new PackageTransfer("query" + databaseName);
                pk.datas = qr;
                oos.writeObject(pk);
                oos.flush();
            } catch (IOException ex) {
                String err = "Has error when sending query\n Try again";
                JOptionPane.showMessageDialog(this, err, "Report", JOptionPane.ERROR_MESSAGE);
                Lb_run.setEnabled(true);
                EditorQuery.setEnabled(true);
            }
        } else {
            String err = "Server is closed\n Reconnect late";
            JOptionPane.showMessageDialog(this, err, "Report", JOptionPane.WARNING_MESSAGE);
        }
    }

    void setEnableSend(boolean b) {
        this.EditorQuery.setEnabled(b);
        this.Lb_run.setEnabled(b);
    }

    private void InitTable() {
        tables.setDoubleBuffered(true);
        tables.setAutoCreateRowSorter(true);
        tables.setCellSelectionEnabled(false);
        tables.setCellEditor(new DefaultCellEditor(new JTextField()));
        jScrollPane1.setViewportView(tables);
        jScrollPane1.paintAll(jScrollPane1.getGraphics());
        ClearTable();
    }

    public void UpdateTable() {        
        TableValues values = new TableValues(listObject, tbHeader);
        values.isEditCell = false;
        tables.setModel(values);
        jScrollPane1.setVisible(true);
        this.paintAll(this.getGraphics());
    }

    public void ClearTable() {
        jScrollPane1.setVisible(false);
    }
}
